////////////////////////////////////////////////
// -- DepthHUD Lite                           //
// by Hurricaaane (Ha3)                       //
//                                            //
// http://www.youtube.com/user/Hurricaaane    //
//--------------------------------------------//
// Elements System                             //
////////////////////////////////////////////////

-- Won't make a metatable because there are so few base functions

local DHLITE_ELEMENTS     = {}
local DHLITE_ELEMENTORDER = {}

function dhlite:GetAllElements()
	return DHLITE_ELEMENTS
	
end

function dhlite:ResetElementData()

end

local DHLITE_STEPS = { 
	[0] = "PerformMath",
	[1] = "DrawUnder",
	[2] = "DrawUnder2D",
	[3] = "DrawOver",
	[4] = "DrawOver2D"
}

function dhlite:DebugElementOps( iStep, viewData, ... )
	local tElementSet = DHLITE_ELEMENTS
	local sStep = DHLITE_STEPS[iStep]
	self:DebugOps( sStep, tElementSet, viewData, ... )
	
end

function dhlite:DebugOps( sStep, tElementSet, viewData, ... )
	for k,objElement in pairs( tElementSet ) do
		if objElement[sStep] and objElement:IsEnabled() then
			objElement[sStep]( objElement, viewData, ... )
			
		end
		
	end
	
end

function dhlite:MountElements( )
	self:ResetElementData()
	
	for tag,objElement in pairs ( DHLITE_ELEMENTS ) do
		if objElement:IsEnabled( ) then
			objElement:Mount( true )
			
		end
		
	end
	
end

function dhlite:UnmountElements( )
	self:ResetElementData()
	
	for tag,objElement in pairs ( DHLITE_ELEMENTS ) do
		objElement:Unmount( true )
		
	end
	
end

function dhlite:OrderElementTable()
	table.sort( DHLITE_ELEMENTORDER, function( a, b )
		return (DHLITE_ELEMENTS[a]:GetBarnstar() == DHLITE_ELEMENTS[b]:GetBarnstar()) and (DHLITE_ELEMENTS[a]:GetDisplayName() < DHLITE_ELEMENTS[b]:GetDisplayName()) or (DHLITE_ELEMENTS[a]:GetBarnstar() > DHLITE_ELEMENTS[b]:GetBarnstar())
		
	end )
	
end

function dhlite:GetElementOrderTable()
	return DHLITE_ELEMENTORDER
end


/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////


local ELEMENT = {}

function ELEMENT:IsEnabled( )
	return dhlite.GetVar("dhlite_elements_enable_" .. self._rawname) > 0
	
end

function ELEMENT:GetDisplayName( )
	return self.Name
	
end

function ELEMENT:GetRawName( )
	return self._rawname
	
end

function ELEMENT:GetDescription( )
	return self.Description or nil
	
end

function ELEMENT:GetBarnstar()
	return dhlite.GetVar( "dhlite_elements_barnstar_" .. self._rawname )
	
end

function ELEMENT:IsMounted()
	return self._IsMounted
end

function ELEMENT:Mount( optbNoTagReset )
	if self._IsMounted then return false end
	
	if self.Load then
		local bOkay, strErr = pcall(function() self:Load() end)
		if not bOkay then Error(" > " .. DHLITE_NAME .. " MountPlugin ERROR [".. self._rawname .."] : ".. strErr) end
	end
	
	for hookName, func in pairs(self.Hooks) do
		hook.Add( hookName , "dhlite_" .. self._rawname .. "_" .. hookName , func )
		
	end
	
	self._IsMounted = true
	
	if not optbNoTagReset then dhlite:ResetElementData() end
	
end

function ELEMENT:Unmount( optbNoTagReset )
	if not self._IsMounted then return false end
	
	for hookName, func in pairs(self.Hooks) do
		hook.Remove( hookName , "dhlite_" .. self._rawname .. "_" .. hookName)
	end
	
	if self.Unload then
		local bOkay, strErr = pcall(function() self:Unload() end)
		if not bOkay then ErrorNoHalt(" > " .. DHLITE_NAME .. " UnmountPlugin ERROR [".. self._rawname .."] : ".. strErr) end
		
	end
	
	self._IsMounted = false
	
	if not optbNoTagReset then dhlite:ResetElementData() end
end

local dhlite_element_meta = {__index=ELEMENT}


function dhlite.GetFilenameCard( )
	return "nothing"
	
end


function dhlite.PrepareElement( objElement, sName )
	if not objElement then return end
	if not sName then
		sName = dhlite.GetFilenameCard( )
		
	end
	sName = string.lower( sName )
	objElement.__namecard = sName
	
	if string.find( sName, " " ) or string.find( sName, "_" ) then
		print("ERROR : Name contains illegal characters.")
		return false
		
	end
	
	if DHLITE_ELEMENTS[sName] then
		print("ERROR : Namecard already exists.")
		return false
		
	end
	
	objElement.HOOK = {}
	
	return true
	
end

-- LIBVAR
function dhlite.RegisterElement( objElement )
	local sName = objElement.__namecard or dhlite.GetFilenameCard( )
	
	--if not objElement or not sName then return end
	if not objElement then return end
	sName = string.lower( sName )
	if string.find( sName, " " ) or string.find( sName, "_" ) or DHLITE_ELEMENTS[sName] then return end
	
	objElement._IsMounted = false
	
	objElement.Name = objElement.Name or ("<" .. sName .. ">")
	objElement._rawname = sName
	
	if objElement.HOOK and (table.Count( objElement.HOOK ) == 0) then
		objElement.HOOK = nil
	end
	
	objElement.Hooks = {}
	if objElement.HOOK then		
		for name, func in pairs( objElement.HOOK ) do
			if type(func) == "function" then
				objElement.Hooks[name] = function(...)
					if not dhlite or not dhlite.IsEnabled or not dhlite.IsEnabled() then return end
					return func( objElement, ... )
					
				end
			end
		end
		
	end
	
	DHLITE_ELEMENTS[sName] = objElement
	table.insert( DHLITE_ELEMENTORDER, sName )
	
	dhlite.CreateVar("dhlite_elements_enable_" .. sName, (objElement.DefaultOn or false) and "1" or "0")
	dhlite.CreateVar("dhlite_elements_barnstar_" .. sName, "0", true, false )
	

	if not DHLITE__CALLBACK_FUNC[ "dhlite_elements_enable_" .. sName ] then
		cvars.AddChangeCallback( "dhlite_elements_enable_" .. sName , function( sCvar, prev, new )
			local sName = string.gsub( sCvar, "dhlite_elements_enable_", "" )
			
			if not dhlite then return end
			if not dhlite.GetAllElements or not dhlite:GetAllElements() or not dhlite:GetAllElements()[ sName ]  then return end
			if (tonumber( new ) <= 0 and tonumber( prev ) <= 0) or (tonumber( new ) > 0 and tonumber( prev ) > 0) then return end
			
			if tonumber( new ) > 0 then
				dhlite:GetAllElements()[ sName ]:Mount()
			
			else
				dhlite:GetAllElements()[ sName ]:Unmount()
				
			end
			
		end)
		DHLITE__CALLBACK_FUNC[ "dhlite_elements_enable_" .. sName ] = true
	
	end
	
	setmetatable(objElement, dhlite_element_meta)
	
	dhlite:OrderElementTable()
	
end
